package com.hzjq.fxlib.ui

import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.view.KeyEvent
import android.view.WindowManager
import android.widget.TextView
import com.hzjq.core.Blast
import com.hzjq.core.bean.*
import com.hzjq.core.callback.Callback
import com.hzjq.core.callback.ProgressCallback
import com.hzjq.core.event.PioUnEnableEvent
import com.hzjq.fxlib.R
import com.hzjq.fxlib.event.BlastEvent
import com.hzjq.fxlib.event.LogEvent
import com.hzjq.fxlib.presenter.AbsViewPresenter
import com.hzjq.fxlib.presenter.BlastErrorPresenter
import com.hzjq.fxlib.presenter.BlastFinishPresenter
import com.hzjq.fxlib.presenter.BlastProgressPresenter
import com.hzjq.fxlib.util.CapCompare
import com.lxj.xpopup.XPopup
import com.lxj.xpopup.core.BasePopupView
import com.lxj.xpopup.impl.ConfirmPopupView
import com.lxj.xpopup.interfaces.OnConfirmListener
import com.lxj.xpopup.interfaces.SimpleCallback
import com.wxl.common.base.AbsActivity
import com.wxl.common.util.DateUtils
import com.wxl.common.util.Toll
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.functions.Consumer
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.activity_blast.*
import kotlinx.android.synthetic.main.activity_charge_layout.*
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode

class BlastActivity : AbsActivity() {


    companion object {
        fun start(context: Context, maxDelay: Long, caps: ArrayList<ErrorCapEntity>) {
            val intent = Intent(context, BlastActivity::class.java)
            intent.putExtra("maxDelay", maxDelay)
            intent.putExtra("caps", caps)
            context.startActivity(intent)
        }
    }

    private val caps = arrayListOf<ErrorCapEntity>()
    private val registerResultCaps = arrayListOf<ErrorCapEntity>()
    private var isBlastEnd = 0
    private var warnPopupView: ConfirmPopupView? = null
    private var maxDelay = 0L
    private var presenters = arrayListOf<AbsViewPresenter>()
    private var position = 0
    private val errorCaps = HashMap<Int,ErrorCapEntity>()
    private val errorCapCounts = HashMap<Int,Int>()
    private val errorCapKeys = arrayListOf<Int>()
    private var disposable: Disposable? = null
    private var blastTime = 0L
    private var blastPoint = -1

    override fun getCreateContentViewId(): Int {
        return R.layout.activity_blast
    }

    override fun onCreateViewChanged() {
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        maxDelay = intent.getLongExtra("maxDelay", 0)
        caps.clear()
        caps.addAll(intent.getSerializableExtra("caps") as ArrayList<ErrorCapEntity>)
        findViewById<TextView>(R.id.titleTextView).textSize = 24f

        presenters.add(BlastProgressPresenter(blastContainer))
        presenters.add(BlastFinishPresenter(blastContainer))
        presenters.add(BlastErrorPresenter(blastContainer))
        presenters[position].show()
        doBlast()
    }


    private fun onExit() {
        val show = XPopup.Builder(this)
            .hasShadowBg(false)
            .asLoading("正在退出...")
            .show()
        closeElectric(show)
    }


    private fun closeElectric(pop: BasePopupView?) {
        Blast.getInstance().charge()
            .onCloseElectric(object : Callback<Boolean> {
                override fun onError(errorCode: ErrorResult) {
                    pop?.dismiss()
                    if (pop != null) {
                        Toll.toll("退出失败")
                    }
                }

                override fun onResult(t: Boolean) {
                    pop?.dismiss()
                    if (t) {
                        Blast.getInstance().blast().cancel()
                        if (pop != null) {
                            finish()
                        }
                    } else {
                        if (pop != null) {
                            Toll.toll("退出失败")
                        }
                    }
                }

                override fun onRetryCountChanged(
                    retryCount: Int,
                    action: String
                ) {

                }

            })
    }




    private fun doBlast() {
        Blast.getInstance().charge().cancel()
        val logEvent = LogEvent("开始起爆")
        blastTime = System.currentTimeMillis()
        logEvent.time = DateUtils.getYMDHMSTime(blastTime)
        logEvent.timeMillis = blastTime
        EventBus.getDefault().post(logEvent)
        isBlastEnd = 1
        Blast.getInstance().blast()
            .onBlast(maxDelay, object : ProgressCallback<CapProgressEntity> {
                override fun onError(errorCode: ErrorResult) {
                    LogEvent.send("爆破","爆破失败",errorCode.errorAction,blastCapDl.text.toString(),blastCapDy.text.toString())
                    isBlastEnd = 0
                    position = 2
                    (presenters[position] as BlastErrorPresenter).isScanEnd(true,registerResultCaps)
                    presenters[position].show()
                    presenters[position].showAction(errorCode.errorAction)
                }

                override fun onProgressChanged(progress: Int, total: Int, action: String) {
                    if(blastPoint < progress/10){
                        blastPoint = progress/10
                        LogEvent.send("爆破","雷管正在爆破","雷管正在爆破，进度:${progress}",blastCapDl.text.toString(),blastCapDy.text.toString())
                    }
                }

                override fun onResult(t: CapProgressEntity) {
                    ("电压:"+t.mVoltage.toString() + "V").also { blastCapDy.text = it }
                    ("电流:"+t.mElectric.toString() + "mA").also { blastCapDl.text = it }
                    if(t.progress == 100) {
                        position = 1
                        presenters[position].show()
                        isBlastEnd = 2
                        showSuccessCap()
                    }
                }

                override fun onRetryCountChanged(retryCount: Int, action: String) {

                }

            }, Consumer<ErrorReadCapEntity> {
                if(it.caps[it.caps.size -1].isScanEnd) {
                    isBlastEnd = 0
                    position = 2
                    presenters[position].show()
                    convertErrorCap(it)
                }
            })
    }

    @SuppressLint("CheckResult")
    private fun convertErrorCap(e: ErrorReadCapEntity){
        disposable?.dispose()

        disposable = Observable.create<Boolean> {
            if(!registerResultCaps.containsAll(e.errors)) {
                registerResultCaps.clear()
                errorCapCounts.clear()
                errorCapKeys.clear()
                errorCaps.clear()
                val temp = arrayListOf<String>()
                e.errors.forEach {
                    if (!temp.contains(it.cap!!.uid)) {
                        CapCompare.compareSetHole(it,caps)
                        registerResultCaps.add(it)
                        temp.add(it.cap!!.uid)
                        if (errorCapCounts.containsKey(it.errorCode)) {
                            errorCapCounts[it.errorCode] = errorCapCounts[it.errorCode]!! + 1
                        } else {
                            errorCapCounts[it.errorCode] = 1
                            errorCapKeys.add(it.errorCode)
                        }
                        errorCaps[it.errorCode] = it
                    }
                }
            }
            it.onNext(e.caps[e.caps.size -1].isScanEnd)
        }.subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                showCaps(it)
            }
    }

    private fun showCaps(isEnd:Boolean) {
//        val size = errorCapKeys.size

//        buffer.append("起爆错误\n")
//        for (i in 0 until size){
//            if(i < errorCapKeys.size){
//                val key = errorCapKeys[i]
//                buffer.append(errorCaps[key]!!.error)
//                    .append("  ")
//                    .append(errorCapCounts[key])
//                    .append("  发雷管")
//            }
//        }

        if(isEnd && registerResultCaps.isNotEmpty()){
            LogEvent.send("爆破","爆破失败","异常雷管${registerResultCaps.size}发",blastCapDl.text.toString(),blastCapDy.text.toString())

            val buffer = StringBuffer()
            buffer.append("异常雷管${registerResultCaps.size}发\n提示:请按F1查看详情")
            (presenters[position] as BlastErrorPresenter).isScanEnd(true,registerResultCaps)
            (presenters[position] as BlastErrorPresenter).showAction(buffer.toString())
        } else {
            val buffer = StringBuffer()
            buffer.append("爆破失败")
            (presenters[position] as BlastErrorPresenter).isScanEnd(true,registerResultCaps)
            (presenters[position] as BlastErrorPresenter).showAction(buffer.toString())

        }
    }

    @SuppressLint("CheckResult")
    private fun showSuccessCap() {
        val eventCaps = arrayListOf<CapEntity>()
        Observable.create<MutableList<CapEntity>> {
            caps.forEach {
                eventCaps.add(it.cap!!)
                it.errorCode = -1
            }
            it.onNext(eventCaps)
        }.subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                LogEvent.send("爆破","爆破完成","${it.size}发雷管已完成爆破",blastCapDl.text.toString(),blastCapDy.text.toString())
                val e = BlastEvent()
                e.caps.addAll(it)
                e.time = blastTime
                EventBus.getDefault().post(e)
            }
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        if(keyCode == KeyEvent.KEYCODE_BACK){
            onBackPressed()
            return true
        }
        return presenters[position].onKeyDown(keyCode, event)
    }


    override fun onBackClick(): Boolean {
        if (isBlastEnd == 0) {
            showWarn(true)
            return false
        } else if (isBlastEnd == 1) {
            Toll.toll("爆破中，请勿操作...")
            return false
        }
        return true
    }

    override fun onBackPressed() {
        if (isBlastEnd == 0) {
            showWarn(true)
        } else {
            if (isBlastEnd == 2) {
                super.onBackPressed()
            } else {
                Toll.toll("爆破中，请勿操作...")
            }
        }
    }


    private fun showWarn(isCancel: Boolean) {
        if (warnPopupView != null && warnPopupView!!.isShow) {
            if (!isCancel) {
                warnPopupView?.dismiss()
            } else {
                return
            }
        }
        if (!isCancel) {
            closeElectric(null)
        }
        warnPopupView = XPopup.Builder(this)
            .dismissOnTouchOutside(false)
            .dismissOnBackPressed(false)
            .setPopupCallback(object : SimpleCallback() {
                override fun onCreated() {
                    if (!isCancel) {
                        warnPopupView?.hideCancelBtn()
                    }
                }
            })
            .asConfirm(
                "警告", "${if (isCancel) "" else "已超时，"}雷管已充入高压，请按相关规定进行执行！", "取消", "确定",
                OnConfirmListener {
                    onExit()
                }, null, !isCancel
            ).show() as ConfirmPopupView
    }

    override fun getPageTitle(): String {
        return "雷管起爆"
    }

    override fun onDestroy() {
        super.onDestroy()
        disposable?.dispose()
        Blast.getInstance().blast().cancel()
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onPioUnEnableEvent(e: PioUnEnableEvent){
        showPioUnEnablePop(this)
    }
}